import time

import coin.exchange.base.kr_ws.ws_client_base as wscb
from coin.exchange.coinone_v2.kr_ws.ws_parser import CoinoneWSParserManager
from coin.exchange.coinone_v2.kr_rest.product import CoinoneProduct
from coin.exchange.base.kr_ws.ws_parser_base import (WsFeedPrinter, WsFeedArchiver)

_ticksize_map = {
    "BTC": 10000,
    "BCH": 500,
    "ETH": 1000,
    "ETC": 10,
    "XRP": 1,
    "QTUM": 10,
    "LTC": 50,
    "IOTA": 10,
    "BTG": 50,
}


class CoinoneWsRequest(wscb.WebsocketRequestBase):
  def FromSingleProduct(product):
    return CoinoneWsRequest(product)

  def __init__(self, product=None):
    self.product = CoinoneProduct.FromAny(product)


class CoinoneWSClient(wscb.WebsocketClientBase):
  RequestType = CoinoneWsRequest

  def __init__(self, request, feed_handler):
    wscb.WebsocketClientBase.__init__(
        self,
        # url="wss://ws.coinone.co.kr:20013",
        url="wss://push.coinone.co.kr/socket.io/?EIO=3&transport=websocket",
        request=request,
        handler=CoinoneWSParserManager(feed_handler, request.product.base))

  def _connect_impl(self):
    symbol = self._request.product.base
    assert symbol == symbol.upper()
    # Receive first message: 0{"sid":"XXXXX","upgrades":[],"pingInterval":25000,"pingTimeout":60000}
    last_msg = self._recv()
    assert last_msg.msg.startswith("0{")

    self._send("40/ticker")
    last_msg = self._recv()
    assert last_msg.msg == "40"

    self._send("40/orderbook")
    self._send("40/trade_%s" % (symbol.lower()))
    self._send("40/mytrade")
    self._recv()
    self._recv()
    self._recv()

    self._send('42/orderbook,["subscribe","%s",%d]' % (symbol, _ticksize_map[symbol]))
    self._recv()

    self._send("""42/orderbook,["get_market_bid",null,null,"%s"]""" % (symbol.lower()))
    self._send("""42/orderbook,["get_market_ask",0,null,"%s"]""" % (symbol.lower()))

    # Subsequently 42/orderbook with correct range of bid/ask should
    # be sent, but feed seems working without it. So use 0,null.

  def _disconnect_impl(self):
    pass

  def _heartbeat_impl(self):
    symbol = self._request.product.base
    assert symbol == symbol.upper()
    self._send("""42/orderbook,["get_market_bid",null,null,"%s"]""" % (symbol.lower()))
    self._send("""42/orderbook,["get_market_ask",0,null,"%s"]""" % (symbol.lower()))


if __name__ == "__main__":
  request = CoinoneWsRequest("ETH-KRW")
  wsClient = CoinoneWSClient(request, WsFeedPrinter(verbose=True))
  wsClient.start()
  wsClient.printInfo()
  while (wsClient.getRecvMsgCount() < 100):
    print("RecvMsgCount =", "%i" % wsClient.getRecvMsgCount())
    time.sleep(1)
  wsClient.stop()
